﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace Sunny.Lib
{
    /// <summary>
    /// It's logger tool, 
    /// It's contains three EventLevel, they were Information,Worning and Error
    /// Log message can save in file(LoggerCarrier.File),windows event(LoggerCarrier.WindowEvent) or both of them, 
    ///     you can change by setting "LoggerCarrier" property value, By default, it's value is LoggerCarrier.File
    /// CreateDate:2012-7-1
    /// Person:Sunny
    /// </summary>
    public class Logger
    {
        public static string logPath;
        public static string LogPath
        {
            get
            {
                if (string.IsNullOrEmpty(logPath))
                {
                    string path = EnvironmentHelper.CurrentDir;
                    logPath = string.Format(@"{0}\Log\", path);
                }
                return logPath;
            }
        }

        private static string filePath
        {
            get
            {
                string path = EnvironmentHelper.CurrentDir;
                return string.Format("{0}/Log/{1}", path, DateTime.Now.ToString("yyyy-MM"));
            }
        }

        private static string fileName
        {
            get
            {
                return DateTime.Now.ToString("yyyy-MM-dd") + ".log";
            }
        }

        private static LoggerCarrier loggerCarrier = Lib.LoggerCarrier.File;
        public static LoggerCarrier LoggerCarrier
        {
            get
            {
                return loggerCarrier;
            }
            set
            {
                loggerCarrier = value;
            }
        }

        public static void LogEvent(string details, EventLevel level = EventLevel.Error, string stackTrace = null)
        {
            EventInfo eventInfo = new EventInfo(level, DateTime.Now) { StackTrace = stackTrace, Details = details };
            LogEvent(eventInfo);
        }

        public static void LogEvent(EventInfo eventInfo)
        {
            InternelLogEvent(eventInfo);
        }

        #region Private methods
        private static void InternelLogEvent(EventInfo eventInfo)
        {
            if (eventInfo == null)
            {
                eventInfo = new EventInfo(EventLevel.Error, DateTime.Now);
                eventInfo.StackTrace = typeof(Logger).FullName;
                eventInfo.Details = "EventInfo should not be null";
            }

            if (loggerCarrier == Lib.LoggerCarrier.File)
            {
                LogEventInFile(eventInfo);
            }
            else if (loggerCarrier == Lib.LoggerCarrier.WindowEvent)
            {
                LogEventInWindowsEvent(eventInfo);
            }
            else
            {
                LogEventInFile(eventInfo);
                LogEventInWindowsEvent(eventInfo);
            }
        }

        private static void LogEventInFile(EventInfo eventInfo)
        {
            // e.g. "Info(2012-06-13 08:23:34):exception is throw"
            string message = string.Format("{0}({1:yyyy-MM-dd HH:mm:ss}){2}[Message]:{3}{4}[StackTrace]:{5}",
                eventInfo.EventLevel.ToString(), eventInfo.OccurDateTime.ToString("yyyy-MM-dd HH:mm:ss"), Environment.NewLine,
                eventInfo.Details, Environment.NewLine, eventInfo.StackTrace);
            message += Environment.NewLine + Environment.NewLine;

            FileHelper.CreateFileWithContent(filePath, fileName, message, false);
        }

        private static void LogEventInWindowsEvent(EventInfo eventInfo)
        {
            string message = string.Format("[Message]:{0}{1}[StackTrace]:{2}", eventInfo.Details, Environment.NewLine, eventInfo.StackTrace);
            System.Diagnostics.EventLog.WriteEntry(LoggerConst.EventSource, message, (EventLogEntryType)eventInfo.EventLevel, LoggerConst.EventID);
        }
        #endregion
    }

    public class EventInfo
    {
        public EventInfo(EventLevel level, DateTime occurDateTime)
        {
            EventLevel = level;
            OccurDateTime = occurDateTime;
        }

        public EventLevel EventLevel { get; set; }
        public string StackTrace { get; set; }
        public DateTime OccurDateTime { get; set; }
        public string Details { get; set; }
    }

    public enum EventLevel
    {
        Error = 1,
        Warning = 2,
        Information = 4,
        SuccessAudit = 8,
        FailureAudit = 16,
    }

    public enum LoggerCarrier
    {
        File,           // Log the message in text file
        WindowEvent,    // Log the message in windows event
        Both            // Log the message in both text file and windows event
    }

    public class LoggerConst
    {
        public static string EventSource = "Sunny Application Source";
        public static int EventID = 100;
    }
}
